package caom.wangs.java8.lamda;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.LongStream;

public class Test03 {
    private static long times = 500000000;
    private long start;

    @Before
    public void befor() {
        start = System.currentTimeMillis();
    }

    @After
    public void end() {
        long end = System.currentTimeMillis();
        System.out.println("消耗时间：" + (end - start));
    }

    //Stream并行处理的过程会分而治之，也就是将一个大的任务切分成了多个小任务，这表示每个任务都是
    //一个线程操作。
    //6.4 线程安全问题
    //在多线程的处理下，肯定会出现数据安全问题。如下：

    /*** 普通for循环 消耗时间：138 */
    @Test
    public void test01() {
        System.out.println("普通for循环:");
        long res = 0;
        for (int i = 0; i < times; i++) {
            res += i;
        }
    }

    /*** 串行流处理 * 消耗时间：203 */
    @Test
    public void test02() {
        System.out.println("串行流：serialStream");
        LongStream.rangeClosed(0, times).reduce(0, Long::sum);
    }

    /*** 并行流处理 消耗时间：84 */
    @Test
    public void test03() {
        LongStream.rangeClosed(0, times).parallel().reduce(0, Long::sum);
    }

    @Test
    public void test011() {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            list.add(i);
        }
        System.out.println(list.size());
        List<Integer> listNew = new ArrayList<>();
        // 使用并行流来向集合中添加数据
        //.forEach(s->listNew.add(s));
        list.parallelStream().forEach(listNew::add);
        System.out.println(listNew.size());
    }

    /*** 加同步锁 */
    @Test
    public void test022() {
        List<Integer> listNew = new ArrayList<>();
        Object obj = new Object();
        IntStream.rangeClosed(1, 1000).parallel().forEach(i -> {
            synchronized (obj) {
                listNew.add(i);
            }
        });
        System.out.println(listNew.size());
    }

    /*** 使用线程安全的容器 */
    @Test
    public void test033() {
        Vector v = new Vector();
        Object obj = new Object();
        IntStream.rangeClosed(1, 1000).parallel().forEach(i -> {
            synchronized (obj) {
                v.add(i);
            }
        });
        System.out.println(v.size());
    }

    /*** 将线程不安全的容器转换为线程安全的容器 */
    @Test
    public void test04() {
        List<Integer> listNew = new ArrayList<>();
        // 将线程不安全的容器包装为线程安全的容器
        List<Integer> synchronizedList = Collections.synchronizedList(listNew);
        Object obj = new Object();
        IntStream.rangeClosed(1, 1000).parallel().forEach(i -> {
            synchronizedList.add(i);
        });
        System.out.println(synchronizedList.size());
    }

    /*** 我们还可以通过Stream中的 toArray方法或者 collect方法来操作 * 就是满足线程安全的要求 */
    @Test
    public void test05() {
        List<Integer> listNew = new ArrayList<>();
        Object obj = new Object();
        List<Integer> list = IntStream.rangeClosed(1, 1000).parallel().boxed().collect(Collectors.toList());
        System.out.println(list.size());
    }
}